Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

correctly apply multiple with_prototypes when a context is set #220

Merged
merged 8 commits into from
Oct 30, 2018

Conversation

keith-hall
Copy link
Collaborator

fixes #178 and fixes #160 and also the ASP syntax test failures.

However, due to my limited Rust knowledge, in it's current state, this PR also breaks something - any help anyone can give me here would be highly appreciated! I temporarily removed lvl.captures.as_ref() from line 312 of parser.rs (replaced it with None) as I was getting a compiler error which I don't know how to fix properly:

error[E0597]: `lvl` does not live long enough
   --> src\parsing\parser.rs:312:126
    |
312 |             let with_prototypes = self.stack[proto_start..].iter().flat_map(|lvl| lvl.prototype.iter().map(|ctx| (true, ctx, lvl.captures.as_ref())));
    |                                                                                                            -----             ^^^                   - borrowed value only lives until here
    |                                                                                                            |                 |
    |                                                                                                            |                 borrowed value does not live long enough
    |                                                                                                            capture occurs here
...
369 |     }
    |     - borrowed value needs to live until here

Does anyone know what I need to do to satisfy the borrow checker please?

@keith-hall keith-hall force-pushed the fix_set_with_prototype branch from d4e27a4 to 5885304 Compare October 17, 2018 14:20
@robinst
Copy link
Collaborator

robinst commented Oct 18, 2018

You can use a move closure here:

lvl.prototype.iter().map(move |ctx| (true, ctx, lvl.captures.as_ref()))

(See this blog post)

// a `with_prototype` stays active when the context is `set`
// until the context layer in the stack (where the `with_prototype`
// was initially applied) is popped off.
let mut proto_ids = old_proto_ids.clone().unwrap_or(Vec::new());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it's necessary in this case, but clippy might recommend doing this instead:

unwrap_or_else(|| Vec::new())

The reason is that with unwrap_or, the argument is always constructed, even when the option had a value. With unwrap_or_else, that only happens when it's actually needed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that makes sense, it's what I originally wanted to achieve; updated - thanks.

@@ -1,5 +1,4 @@
loading syntax definitions from testdata/Packages
FAILED testdata/Packages/ASP/syntax_test_asp.asp: 162
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 very nice!

Have you checked if it happens to fix any others of the syntests?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't fix any other tests at the current submodule version, but will allow us to update the sublimehq/Packages submodule and not have failing Java(doc) tests etc.

@keith-hall
Copy link
Collaborator Author

Thanks for that @robinst, it worked perfectly ❤️
I have made the improvements you suggested and also fixed a tiny merge conflict :)

@robinst
Copy link
Collaborator

robinst commented Oct 18, 2018

It's good to finally have these bugs fixed :)!

// a `with_prototype` stays active when the context is `set`
// until the context layer in the stack (where the `with_prototype`
// was initially applied) is popped off.
let mut proto_ids = old_proto_ids.clone().unwrap_or_else(|| Vec::new());
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suppose a set has multiple context refs, this appears to add the old prototypes to each new pushed frame, whereas the old behaviour was to only add the old prototypes to the last pushed frame (see the old else { None } block).

This seems unintended, but maybe it was intended.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice spot, it should in fact keep the old prototypes on the first pushed frame, there is no need to duplicate it on the other frames as it will be applied from the first pushed frame anyway. I've fixed this and added a test which verifies that it matches ST's behavior.

@robinst
Copy link
Collaborator

robinst commented Oct 30, 2018

So after we merge this, we can:

  • Update the packs
  • Release a new version 🎉

Copy link
Owner

@trishume trishume left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@trishume trishume merged commit a09ad08 into trishume:master Oct 30, 2018
@robinst
Copy link
Collaborator

robinst commented Oct 30, 2018

@keith-hall Do you wanna do the honors of raising a PR to update the packs?

@keith-hall keith-hall deleted the fix_set_with_prototype branch October 30, 2018 07:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants